package references

import (
	"jvm/nzpJvm/instructions/base"
	"jvm/nzpJvm/instructions/utils"
	"jvm/nzpJvm/runtime_area"
	"jvm/nzpJvm/runtime_area/heap"
)

// newarray指令用来创建基本类型数组
type NEW_ARRAY struct {
	arrayType uint8 // 一个字节指示数组的类型
}

// newarray指令的第一个操作数是arrayType，标识数组的类型，从字节码中获取
func (self *NEW_ARRAY) FetchOperands(reader *base.BytecodeReader) {
	self.arrayType = reader.ReadUint8()
}

func (self *NEW_ARRAY) Execute(frame *runtime_area.Frame) {
	stack := frame.OperandStack()
	// newarray的第二个操作数是count，表示数组长度，从操作数栈中弹出
	arrayLength := stack.PopInt()
	if arrayLength < 0 {
		panic("java.lang.NegativeArraysSizeException")
	}
	// 加载此类的类加载器
	classLoader := frame.Method().Class().Loader()
	// 获取基本类型数组对应的Class对象
	arrayClass := getPrimitiveArrayClass(classLoader, self.arrayType)
	// 创建指定的长度的基本类型数组对象
	arrayObject := arrayClass.NewArray(uint(arrayLength))
	// 新的数组对象入栈
	stack.PushRef(arrayObject)
}

func getPrimitiveArrayClass(loader *heap.ClassLoader, arrayType uint8) *heap.Class {
	switch arrayType {
	case utils.ARRAY_TYPE_BOOLEAN:
		return loader.LoadArrayClass("[Z")
	case utils.ARRAY_TYPE_CHAR:
		return loader.LoadArrayClass("[C")
	case utils.ARRAY_TYPE_FLOAT:
		return loader.LoadArrayClass("[F")
	case utils.ARRAY_TYPE_DOUBLE:
		return loader.LoadArrayClass("[D")
	case utils.ARRAY_TYPE_BYTE:
		return loader.LoadArrayClass("[B")
	case utils.ARRAY_TYPE_SHORT:
		return loader.LoadArrayClass("[S")
	case utils.ARRAY_TYPE_INT:
		return loader.LoadArrayClass("[I")
	case utils.ARRAY_TYPE_LONG:
		return loader.LoadArrayClass("[J")
	default:
		panic("invalid array type")
	}
}
